﻿using System;
using System.Xml.XPath;
using System.Collections.Generic;

namespace Songhay.Data.GenericWeb.InputDefinitions
{
    using Songhay.Data.GenericWeb.DataTransferContracts;
    using Songhay.Xml;

    /// <summary>
    /// Defines input for the Document data transfer contract.
    /// </summary>
    public class InputDocument : IDocument
    {
        /// <summary>
        /// Processes data for the delete command.
        /// </summary>
        /// <param name="navigableInput">The navigable input.</param>
        /// <returns>Returns the Document data transfer contract.</returns>
        public static IDocument InputDelete(IXPathNavigable navigableInput)
        {
            InputDocument inputDocument = new InputDocument();
            XPathNavigator node = XmlUtility.GetNavigableNode(navigableInput, "//FormData");

            int? id = FrameworkType.ParseInt32(XmlUtility.GetNodeValue(node, "./DocumentId", true));
            inputDocument.DocumentId = id;

            return inputDocument;
        }

        /// <summary>
        /// Processes data for the insert command.
        /// </summary>
        /// <param name="navigableInput">The navigable input.</param>
        /// <returns>Returns the Document data transfer contract.</returns>
        public static IDocument InputInsert(IXPathNavigable navigableInput)
        {
            InputDocument inputDocument = new InputDocument();
            XPathNavigator node = XmlUtility.GetNavigableNode(navigableInput, "//FormData");

            object p = null;
            p = XmlUtility.GetNodeValue(node, "./SegmentId", false);
            inputDocument.SegmentId = FrameworkType.ParseInt32(p);

            p = XmlUtility.GetNodeValue(node, "./Title", true);
            inputDocument.Title = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValue(node, "./DocumentShortName", true);
            inputDocument.DocumentShortName = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValue(node, "./FileName", true);
            inputDocument.FileName = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValue(node, "./Path", true);
            inputDocument.Path = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValueAndParse<DateTime>(node, "./CreateDate", true, DateTime.Now);
            inputDocument.CreateDate = FrameworkType.ParseDateTime(p);

            p = XmlUtility.GetNodeValueAndParse<DateTime>(node, "./ModificationDate", true, DateTime.Now);
            inputDocument.ModificationDate = FrameworkType.ParseDateTime(p);

            p = XmlUtility.GetNodeValue(node, "./TemplateId", true);
            inputDocument.TemplateId = FrameworkType.ParseInt32(p);

            p = XmlUtility.GetNodeValue(node, "./IsRoot", true);
            inputDocument.IsRoot = FrameworkType.ParseBoolean(p, true);

            p = XmlUtility.GetNodeValue(node, "./IsActive", true);
            inputDocument.IsActive = FrameworkType.ParseBoolean(p, true);

            p = XmlUtility.GetNodeValue(node, "./SortOrdinal", true);
            inputDocument.SortOrdinal = FrameworkType.ParseByte(p);

            p = XmlUtility.GetNodeValue(node, "./ClientId", true);
            inputDocument.ClientId = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValue(node, "./Tag", true);
            inputDocument.Tag = FrameworkType.ParseString(p);

            return inputDocument;
        }

        /// <summary>
        /// Processes data for the update command.
        /// </summary>
        /// <param name="navigableInput">The navigable input.</param>
        /// <returns>Returns the Document data transfer contract.</returns>
        public static IDocument InputUpdate(IXPathNavigable navigableInput)
        {
            IDocument inputDocument = InputDocument.InputInsert(navigableInput);
            XPathNavigator node = XmlUtility.GetNavigableNode(navigableInput, "//FormData");

            object p = null;

            p = XmlUtility.GetNodeValue(node, "./DocumentId", true);

            if(FrameworkType.ObjectIsNullOrEmptyString(p))
                throw new Exception("Document ID cannot be null or empty.");

            inputDocument.DocumentId = FrameworkType.ParseInt32(p);

            return inputDocument;
        }

        #region IDocument Members

        /// <summary>
        /// Gets or sets the Client ID.
        /// </summary>
        /// <value>The Client ID.</value>
        public string ClientId
        {
            get
            {
                return this._clientId;
            }
            set
            {
                this._clientId = value;
            }
        }

        /// <summary>
        /// Gets or sets the create date.
        /// </summary>
        /// <value>The create date.</value>
        public DateTime? CreateDate
        {
            get
            {
                return this._createDate;
            }
            set
            {
                this._createDate = value;
            }
        }

        /// <summary>
        /// Gets or sets the Document ID.
        /// </summary>
        /// <value>The Document ID.</value>
        public int? DocumentId
        {
            get
            {
                return this._documentId;
            }
            set
            {
                this._documentId = value;
            }
        }

        /// <summary>
        /// Gets or sets the short name of the Document.
        /// </summary>
        /// <value>The short name of the Document.</value>
        public string DocumentShortName
        {
            get
            {
                return this._documentShortName;
            }
            set
            {
                this._documentShortName = value;
            }
        }

        /// <summary>
        /// Gets or sets the name of the file.
        /// </summary>
        /// <value>The name of the file.</value>
        public string FileName
        {
            get
            {
                return this._fileName;
            }
            set
            {
                this._fileName = value;
            }
        }

        /// <summary>
        /// Gets or sets whether the Document is active.
        /// </summary>
        /// <value>The Document is active?</value>
        public bool? IsActive
        {
            get
            {
                return this._isActive;
            }
            set
            {
                this._isActive = value;
            }
        }

        /// <summary>
        /// Gets or sets whether the Document is the root of a Segment.
        /// </summary>
        /// <value>The Document is the root?</value>
        public bool? IsRoot
        {
            get
            {
                return this._isRoot;
            }
            set
            {
                this._isRoot = value;
            }
        }

        /// <summary>
        /// Gets or sets the modification date.
        /// </summary>
        /// <value>The modification date.</value>
        public DateTime? ModificationDate
        {
            get
            {
                return this._modificationDate;
            }
            set
            {
                this._modificationDate = value;
            }
        }

        /// <summary>
        /// Gets or sets the path.
        /// </summary>
        /// <value>The path.</value>
        public string Path
        {
            get
            {
                return this._path;
            }
            set
            {
                this._path = value;
            }
        }

        /// <summary>
        /// Gets or sets the Segment ID.
        /// </summary>
        /// <value>The Segment ID.</value>
        public int? SegmentId
        {
            get
            {
                return this._segmentId;
            }
            set
            {
                this._segmentId = value;
            }
        }

        /// <summary>
        /// Gets or sets the sort ordinal.
        /// </summary>
        /// <value>The sort ordinal.</value>
        public byte? SortOrdinal
        {
            get
            {
                return this._sortOrdinal;
            }
            set
            {
                this._sortOrdinal = value;
            }
        }

        /// <summary>
        /// Gets or sets the tag.
        /// </summary>
        /// <value>The tag.</value>
        public string Tag
        {
            get
            {
                return this._tag;
            }
            set
            {
                this._tag = value;
            }
        }

        /// <summary>
        /// Gets or sets the template ID.
        /// </summary>
        /// <value>The template ID.</value>
        public int? TemplateId
        {
            get
            {
                return this._templateId;
            }
            set
            {
                this._templateId = value;
            }
        }

        /// <summary>
        /// Gets or sets the title.
        /// </summary>
        /// <value>The title.</value>
        public string Title
        {
            get
            {
                return this._title;
            }
            set
            {
                this._title = value;
            }
        }

        #endregion

        private string _clientId;
        private DateTime? _createDate;
        private int? _documentId;
        private string _documentShortName;
        private string _fileName;
        private bool? _isActive;
        private bool? _isRoot;
        private DateTime? _modificationDate;
        private string _path;
        private int? _segmentId;
        private byte? _sortOrdinal;
        private string _tag;
        private int? _templateId;
        private string _title;
    }
}
